package edu.pku.hawk.sandbox;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.jms.MessageListener;
import javax.servlet.http.HttpServletRequest;

import edu.pku.hawk.controller.util.Constants;
import edu.pku.hawk.controller.util.MConsumerQueue;
import edu.pku.hawk.controller.util.MProducerQueue;
import edu.pku.hawk.controller.util.MQManager;
import edu.pku.hawk.controller.util.MQueue;
import edu.pku.hawk.controller.util.ProcDes;
import edu.pku.hawk.controller.util.Scenario;
import edu.pku.hawk.controller.util.SerResource;
import edu.pku.hawk.controller.util.SerResourceList;
import flex.messaging.FlexContext;
import flex.messaging.MessageBroker;
import flex.messaging.messages.AsyncMessage;
import flex.messaging.messages.Message;
import flex.messaging.services.MessageService;
import flex.messaging.services.ServiceAdapter;
import flex.messaging.util.UUIDUtils;

public class FusionServiceAdapter  extends ServiceAdapter{
	
	private static Logger logger=Logger.getLogger(FusionServiceAdapter.class.getName());
	
	private List<SerResource> services;
	
	public FusionServiceAdapter(){
	
	}
	
	public void start() {
		System.out.println("FusionServiceAdapter started");
		listenQueue();
	}
	
	public void stop(){
		System.out.println("FusionServiceAdapter stopped");
	}
	
	
	/**
	 * get the current client Ip
	 * @return
	 */
	private String getClientIp()
	{
		HttpServletRequest request=FlexContext.getHttpRequest();
		return request.getRemoteAddr();
	}
	
	private void listenQueue(){
		MQManager mgr=null;
		try{
			mgr=MQManager.getInstance();
			MConsumerQueue queue = mgr.getConsumerQueue(Constants.Ctrl_UI_ServiceProfile_QueueName);
			final String clientId = UUIDUtils.createUUID();
			final MessageBroker msgBroker = MessageBroker.getMessageBroker(null);
			queue.setMessageListener(new MessageListener() {
				@Override
				public void onMessage(javax.jms.Message message) {
					try {
						SerResourceList serList = (SerResourceList) MQueue.toOjbect(message);
						services=serList.ResourceList;
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			});
			
			queue = mgr.getConsumerQueue(Constants.Ctrl_UI_ClearSandResponse_QueueName);
			queue.setMessageListener(new MessageListener() {
				@Override
				public void onMessage(javax.jms.Message message) {
					try {
						String retMsg=MQueue.toString(message);
						System.out.println(retMsg);
						AsyncMessage msg = new AsyncMessage();
						msg.setDestination("FusionServiceMessage");
						msg.setClientId(clientId);
						msg.setMessageId(UUIDUtils.createUUID());
						// get message..
						FusionServiceMessage mymsg=new FusionServiceMessage();
						mymsg.setMessageType(FusionServiceMessage.TYPE_CLEAR_RESPONSE);
						mymsg.setMessageValue(retMsg);
						msg.setBody(mymsg);
						msgBroker.routeMessageToService(msg, null);
						
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			});
			
			
			queue = mgr.getConsumerQueue(Constants.Ctrl_UI_ProcConfirm_QueueName);
			queue.setMessageListener(new MessageListener() {
				@Override
				public void onMessage(javax.jms.Message message) {
					try {
						Object retObj=MQueue.toOjbect(message);
						System.out.println("---------------receive proc confirm message------------");
						AsyncMessage msg = new AsyncMessage();
						msg.setDestination("FusionServiceMessage");
						msg.setClientId(clientId);
						msg.setMessageId(UUIDUtils.createUUID());
						// get message..
						FusionServiceMessage mymsg=new FusionServiceMessage();
						mymsg.setMessageType(FusionServiceMessage.TYPE_FUSE_RESPONSE);
						mymsg.setMessageValue(retObj);
						msg.setBody(mymsg);
						msgBroker.routeMessageToService(msg, null);
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			});
		}catch (Exception ex) {
			ex.printStackTrace();
			if (mgr != null) {
				try {
					mgr.close();
				} catch (Exception eex) {
					ex.printStackTrace();
				}
			}
		}
		
	}

	//Read service information from database
	private List<SerResource> generateServiceList(){
		if(services==null){
			services=new ArrayList<SerResource>();
			services.add(new SerResource(Constants.TYPE_INFRARED_SENSOR,"红外传感服务","images/Infrared.png",SerResource.BASISTYPE,1.2,10,100,10));
			services.add(new SerResource(Constants.TYPE_METAL_SENSOR,"金属传感服务","images/metal.png",SerResource.BASISTYPE,1.2,10,100,10));
			services.add(new SerResource(Constants.TYPE_PRESSURE_SENSOR,"压力传感服务","images/pressure.png",SerResource.BASISTYPE,1.2,10,100,10));
			services.add(new SerResource(Constants.TYPE_RFID_SENSOR,"RFID传感服务","images/rfid.png",SerResource.BASISTYPE,1.2,10,100,10));
			services.add(new SerResource(Constants.TYPE_SOUND_SENSOR,"声音传感服务","images/sound.png",SerResource.BASISTYPE,1.2,10,100,10));
			services.add(new SerResource(Constants.TYPE_VIBRATE_SENSOR,"震动传感服务","images/vibrate.png",SerResource.BASISTYPE,1.2,10,100,10));
			services.add(new SerResource(Constants.TYPE_TRACK,"轨迹融合服务","images/combination.png",SerResource.COMPOSEDTYPE,1.2,10,100,10));
			services.add(new SerResource(Constants.TYPE_IDENTIFY,"目标识别服务","images/identify.png",SerResource.COMPOSEDTYPE,1.2,10,100,10));
		}
		return services;
	}
	
	private boolean sendFuseService(Scenario scenario) {
		MQManager mgr=null;
		try {
			mgr=MQManager.getInstance();
			ProcDes procDes = new ProcDes();
			procDes.isConbine = scenario.isCreateVM();
			procDes.scenarioName=scenario.getName();
			procDes.clientIP=scenario.getClientIP();
			int[] detectorTypes = new int[scenario.getServiceIds().size()];
			for (int i = 0; i < detectorTypes.length; i++) {
				detectorTypes[i] = Integer.parseInt((String)scenario.getServiceIds().get(i));
			}
			procDes.detectorTypes = detectorTypes;
			
			logger.info("===create vm: "+procDes.isConbine);
			logger.info("===scenario name: "+procDes.scenarioName);
			logger.info("===client ip: "+procDes.clientIP);
			logger.info("===process ids: "+scenario.getServiceIds());
			
			MProducerQueue producerQueue = mgr.getProducerQueue(Constants.Ctrl_UI_Proc_QueueName);
			producerQueue.send(procDes);
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}
		return true;
	}
	
	
	private boolean sendClearService()
	{
		MQManager mgr=null;
		try {
			mgr=MQManager.getInstance();
			MProducerQueue producerQueue = mgr.getProducerQueue(Constants.Ctrl_UI_ClearSandRequest_QueueName);
			producerQueue.send(Constants.Cmd_ClearSand_Request);
			
			System.out.println("send clear service");
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}
		return true;
	}
	
	 
	@Override
	public Object invoke(Message msg) {
		FusionServiceMessage msgObj=(FusionServiceMessage)msg.getBody();
		FusionServiceMessage retMsgObj=new FusionServiceMessage();
		if(msgObj.getMessageType()==FusionServiceMessage.TYPE_GETSERVICES){
			retMsgObj.setMessageType(FusionServiceMessage.TYPE_GETSERVICES);
			retMsgObj.setMessageValue(generateServiceList());
		}else if(msgObj.getMessageType()==FusionServiceMessage.TYPE_FUSE_REQUEST){
			Scenario scenario=(Scenario)msgObj.getMessageValue();
			scenario.setClientIP(getClientIp());
			boolean success=sendFuseService(scenario);
			retMsgObj.setMessageType(FusionServiceMessage.TYPE_FUSE_REQUEST);
			retMsgObj.setMessageValue(success);
		}else if(msgObj.getMessageType()==FusionServiceMessage.TYPE_FUSE_RESPONSE){
			AsyncMessage newMessage = (AsyncMessage) msg;
			MessageService msgService = (MessageService) getDestination().getService();
			msgService.pushMessageToClients(newMessage, true);
		}else if(msgObj.getMessageType()==FusionServiceMessage.TYPE_CLEAR_REQUEST){
			boolean success=sendClearService();
			retMsgObj.setMessageType(FusionServiceMessage.TYPE_CLEAR_REQUEST);
			retMsgObj.setMessageValue(success);
		}else if(msgObj.getMessageType()==FusionServiceMessage.TYPE_CLEAR_RESPONSE){
			AsyncMessage newMessage = (AsyncMessage) msg;
			MessageService msgService = (MessageService) getDestination().getService();
			msgService.pushMessageToClients(newMessage, true);
		}
		else{
			retMsgObj.setMessageType(FusionServiceMessage.TYPE_UNKNOWN);
			retMsgObj.setMessageValue(null);
		}
		return retMsgObj;	
	}
}
